from datetime import datetime

from fastapi_pagination.bases import AbstractPage
from fastapi_pagination.ext.databases import paginate
from sqlalchemy import insert, select, update

from forward.api.admin.schemas.common import (
    CommonAlbumListInSchema,
    CommonAlbumCateListInSchema,
    CommonAlbumCateOutSchema,
    CommonAlbumCateEditInSchema,
    CommonAlbumAddInSchema,
    CommonAlbumCateDelInSchema,
    CommonAlbumRenameInSchema,
    CommonAlbumMoveInSchema,
    CommonAlbumDelInSchema,
    CommonAlbumOutSchema,
)
from forward.dependencies.database import db
from forward.model.tables.common import AlbumModel, AlbumCateModel
from forward.utils.array import ArrayUtil
from forward.utils.urls import UrlUtil


class AlbumService:
    """主页服务实现类"""

    async def album_list(
        self, params: CommonAlbumListInSchema
    ) -> AbstractPage[CommonAlbumOutSchema]:
        where = [AlbumModel.is_delete == 0]
        if params.cid is not None:
            where.append(AlbumModel.cid == params.cid)
        if params.type:
            where.append(AlbumModel.type == params.type)
        if params.keyword:
            where.append(AlbumModel.name.like("%{0}%".format(params.keyword)))
        query = (
            select(AlbumModel)
            .select_from(AlbumModel)
            .where(*where)
            .order_by(AlbumModel.id)
        )

        pager = await paginate(db, query)
        for row in pager.lists:
            row.url = await UrlUtil.to_absolute_url(row.uri)
        return pager

    async def album_rename(self, params: CommonAlbumRenameInSchema):
        _id = params.id
        album = await db.fetch_one(
            select(AlbumModel.id, AlbumModel.name)
            .select_from(AlbumModel)
            .where(AlbumModel.id == _id, AlbumModel.is_delete == 0)
        )
        assert album, "文件丢失！"
        album_dict = {"name": params.name}
        return await db.execute(
            update(AlbumModel).where(AlbumModel.id == _id).values(**album_dict)
        )

    async def album_move(self, params: CommonAlbumMoveInSchema):
        """
        文件移动
        :param params:
        :return:
        """
        cid = params.cid
        ids = params.ids
        albums = await db.fetch_all(
            select(AlbumModel.id, AlbumModel.name)
            .select_from(AlbumModel)
            .where(AlbumModel.id.in_(ids), AlbumModel.is_delete == 0)
        )
        assert albums, "文件丢失！"

        if cid > 0:
            assert await db.fetch_one(
                select(
                    AlbumCateModel.id,
                    AlbumCateModel.name,
                )
                .select_from(AlbumCateModel)
                .where(AlbumCateModel.id == cid, AlbumCateModel.is_delete == 0)
            ), "分类已不存在"
        return await db.execute_many(
            update(AlbumModel).where(AlbumModel.id.in_(ids)),
            [{"cid": cid}],
        )

    async def album_add(self, params: CommonAlbumAddInSchema):
        """
        文件新增
        :param params:
        :return:
        """
        create_dict = {
            "cid": params.cid,
            "aid": params.aid,
            "uid": params.uid,
            "name": params.name,
            "ext": params.ext,
            "uri": params.url,
            "size": params.size,
            "type": params.type,
            
        }
        query = insert(AlbumModel).values(**create_dict)
        return await db.execute(query)

    async def album_del(self, params: CommonAlbumDelInSchema):
        """
        文件删除
        :param params:
        :return:
        """
        ids = params.ids
        albums = await db.fetch_all(
            select(AlbumModel.id, AlbumModel.name)
            .select_from(AlbumModel)
            .where(AlbumModel.id.in_(ids), AlbumModel.is_delete == 0)
        )
        assert albums, "文件丢失！"
        return await db.execute_many(
            update(AlbumModel).where(AlbumModel.id.in_(ids)),
            [{"is_delete": 1, "deleted_time": datetime.now()}],
        )

    async def cate_list(self, params: CommonAlbumCateListInSchema):
        """
        分类列表
        :param params:
        :return:
        """
        _type = params.type
        keyword = params.keyword
        where = [AlbumCateModel.is_delete == 0]
        if _type:
            where.append(AlbumCateModel.type == _type)
        if keyword:
            where.append(AlbumCateModel.name.like("%{0}%".format(keyword)))

        cate_list = await db.fetch_all(
            select(AlbumCateModel)
            .select_from(AlbumCateModel)
            .where(*where)
            .order_by(AlbumCateModel.id)
        )
        return ArrayUtil.list_to_tree(
            [
                CommonAlbumCateOutSchema.model_validate(
                    i, from_attributes=True
                ).model_dump()
                for i in cate_list
            ],
            "id",
            "pid",
            "children",
        )

    async def cate_add(self, params: CommonAlbumCateEditInSchema):

        if params.pid and params.pid > 0:
            assert await db.fetch_one(
                select(
                    AlbumCateModel.id,
                    AlbumCateModel.name,
                )
                .select_from(AlbumCateModel)
                .where(
                    AlbumCateModel.id == params.pid,
                    AlbumCateModel.is_delete == 0,
                )
            ), "父级分类不存在"

        create_dict = {
            "type": params.type,
            "pid": params.pid,
            "name": params.name,
            
        }
        query = insert(AlbumCateModel).values(**create_dict)
        return await db.execute(query)

    async def cate_rename(self, params: CommonAlbumRenameInSchema):
        _id = params.id
        name = params.name
        assert await db.fetch_one(
            select(
                AlbumCateModel.id,
                AlbumCateModel.name,
            )
            .select_from(AlbumCateModel)
            .where(AlbumCateModel.id == _id, AlbumCateModel.is_delete == 0)
        ), "分类已不存在"
        edit_cate = {"name": name}
        return await db.execute(
            update(AlbumCateModel).where(AlbumCateModel.id == _id).values(**edit_cate)
        )

    async def cate_del(self, params: CommonAlbumCateDelInSchema):
        _id = params.id
        assert await db.fetch_one(
            select(AlbumCateModel.id, AlbumCateModel.name)
            .select_from(AlbumCateModel)
            .where(AlbumCateModel.id == _id, AlbumCateModel.is_delete == 0)
        ), "分类已不存在"

        assert not await db.fetch_one(
            select(AlbumCateModel.id, AlbumCateModel.name)
            .select_from(AlbumCateModel)
            .where(AlbumCateModel.pid == _id, AlbumCateModel.is_delete == 0)
        ), "当前分类正被使用中,不能删除！"

        assert not await db.fetch_one(
            select(AlbumModel.id, AlbumModel.name)
            .select_from(AlbumModel)
            .where(AlbumModel.cid == params.id, AlbumModel.is_delete == 0)
        ), "当前分类正被使用中,不能删除！"

        return await db.execute(
            update(AlbumCateModel)
            .where(AlbumCateModel.id == _id)
            .values(is_delete=1, deleted_time=datetime.now())
        )

    @classmethod
    async def instance(cls):
        """实例化"""
        return cls()
